#include <iostream>
#include <cassert>

#include "crbt/MeanIC.h"
#include "crbt/SmoothIC.h"
#include "crbt/SumIC.h"
#include "crbt/SignalFilterIC.h"
#include "crbt/VarianceIC.h"
#include "crbt/DecisionMakingUnit.h"

bool nearlyEqual(double a, double b)
{
    return std::abs(a - b) < 2e-6;
}

void TestCircularBufferPushBack()
{
    CircularBuffer<int> buffer(5);
    buffer.push_back(1);
    buffer.push_back(2);
    buffer.push_back(3);
    buffer.push_back(4);
    buffer.push_back(5);

    assert(buffer[0] == 1);
    assert(buffer[1] == 2);
    assert(buffer[2] == 3);
    assert(buffer[3] == 4);
    assert(buffer[4] == 5);

    buffer.push_back(6); // This should overwrite the first element
    assert(buffer[0] == 2);
    assert(buffer[1] == 3);
    assert(buffer[2] == 4);
    assert(buffer[3] == 5);
    assert(buffer[4] == 6);

    assert(buffer[-1] == 6);
    assert(buffer[-2] == 5);
    assert(buffer[-3] == 4);
    assert(buffer[-4] == 3);
    assert(buffer[-5] == 2);
    std::cout << "TestCircularBufferPushBack passed." << std::endl;
}

void TestCircularBufferClear()
{
    CircularBuffer<int> buffer(5);
    for (int i = 0; i < buffer.capacity; ++i)
    {
        buffer.push_back(i + 1);
    }

    buffer.clear();
    for (int i = 0; i < buffer.capacity; ++i)
    {
        assert(buffer[i] == 0); // Assuming default constructor initializes to 0
    }

    std::cout << "TestCircularBufferClear passed." << std::endl;
}

void TestCircularBufferOutOfRange()
{
    CircularBuffer<int> buffer(5);
    buffer.push_back(1);
    buffer.push_back(2);

    bool exceptionThrown = false;
    try
    {
        buffer[5];
    }
    catch (const std::out_of_range &e)
    {
        exceptionThrown = true;
    }
    assert(exceptionThrown);

    exceptionThrown = false;
    try
    {
        buffer[-6];
    }
    catch (const std::out_of_range &e)
    {
        exceptionThrown = true;
    }
    assert(exceptionThrown);

    std::cout << "TestCircularBufferOutOfRange passed." << std::endl;
}

void TestCircularLenthEqualsOne()
{
    CircularBuffer<int> buffer(1);
    for (int i = 0; i < 10; ++i)
    {
        buffer.push_back(i);
        assert(buffer[0] == i);
        assert(buffer[-1] == i);
    }
    std::cout << "TestCircularLenthEqualsOne passed." << std::endl;
}

void TestMeanIC()
{
    // 测试double类型
    MeanIC meanICDouble(3);
    assert(meanICDouble.update(1) == 1.0); // 一个数据点，平均值应为1.0
    assert(meanICDouble.update(2) == 1.5); // 两个数据点，平均值应为1.5
    assert(meanICDouble.update(3) == 2.0); // 三个数据点，平均值应为2.0
    assert(meanICDouble.update(4) == 3.0); // 周期满，平均值应为3.0

    // 测试reset方法
    meanICDouble.reset();
    assert(meanICDouble.update(1.5) == 1.5); // 重置后，结果应为0.0

    std::cout << "All MeanIC tests passed successfully." << std::endl;
}

void TestSumIC()
{
    // 测试double类型
    SumIC<double> sumICDouble(3);
    assert(sumICDouble.update(1.0) == 1.0); // 累加1.0
    assert(sumICDouble.update(2.0) == 3.0); // 累加2.0
    assert(sumICDouble.update(3.0) == 6.0); // 累加3.0
    assert(sumICDouble.update(4.0) == 9.0); // 累加4.0，并减去第一个1.0

    // 测试int类型
    SumIC<int> sumICInt(3);
    assert(sumICInt.update(1) == 1); // 累加1
    assert(sumICInt.update(2) == 3); // 累加2
    assert(sumICInt.update(3) == 6); // 累加3
    assert(sumICInt.update(4) == 9); // 累加4，并减去第一个1

    std::cout << "All SumIC tests passed successfully." << std::endl;
}

void TestSmoothIC()
{
    // 测试double类型
    SmoothIC smoothICDouble;
    assert(smoothICDouble.update(1.0) == 1.0);
    assert(smoothICDouble.update(3.0) == 3.0);
    assert(smoothICDouble.update(1.0) == 1.0);
    assert(smoothICDouble.update(1.0) == 1.0);
    assert(smoothICDouble.update(2.0) == 1.0);
    assert(smoothICDouble.update(2.0) == 2.0);
    assert(smoothICDouble.update(3.0) == 2.0);
    assert(smoothICDouble.update(4.0) == 4.0);

    // 测试int类型
    SmoothIC<int> smoothICInt;
    assert(smoothICInt.update(1) == 1);
    assert(smoothICInt.update(1) == 1);
    assert(smoothICInt.update(2) == 1);
    assert(smoothICInt.update(2) == 2);

    // 测试bool类型
    SmoothIC<bool> smoothICBool;
    assert(smoothICBool.update(true) == true);
    assert(smoothICBool.update(true) == true);
    assert(smoothICBool.update(false) == true);
    assert(smoothICBool.update(false) == false);

    std::cout << "All SmoothIC tests passed successfully." << std::endl;
}

void TestDecisionMakingUnit()
{
    class MyDMU : DecisionMakingUnit<int>
    {
    public:
        Decision on_market_data(const int &new_data)
        {
            Decision decision(0, 0);
            decision.result_value = new_data;
            return decision;
        }
    };

    MyDMU d;
    assert(d.on_market_data(5).result_value == 5);
    std::cout << "All DecisionMakingUnit tests passed successfully." << std::endl;
}

void TestSignalFilterIC()
{
    SignalFilterIC<double> filter;

    // 测试同一个轮次，第一次返回非0值
    assert(filter.update({1.0, 1}) == 1);
    assert(filter.update({1.0, 1}) == 0);
    assert(filter.update({1.0, 1}) == 0);

    // 测试轮次改变，第一次返回非0值
    assert(filter.update({2.0, 1}) == 1);
    // 测试轮次改变，第二次返回非0值
    assert(filter.update({2.0, 1}) == 0);
    assert(filter.update({2.0, 0}) == 0);

    // 测试轮次改变，非0值
    assert(filter.update({3.0, 0}) == 0);
    assert(filter.update({3.0, 0}) == 0);
    assert(filter.update({3.0, 0}) == 0);
    assert(filter.update({3.0, 1}) == 1);

    // 测试轮次改变，第一次返回非0值
    assert(filter.update({2.0, 0}) == 0);
    assert(filter.update({2.0, 888}) == 888);
    assert(filter.update({2.0, 0}) == 0);

    // 测试轮次改变，第一次返回非0值
    assert(filter.update({2.0, 1}) == 0);
    assert(filter.update({2.0, 1}) == 0);
    assert(filter.update({2.0, 0}) == 0);

    // 测试重置函数
    filter.reset();
    // 测试重置后，第一次返回非0值
    assert(filter.update({1.0, 0}) == 0);
    assert(filter.update({1.0, 1}) == 1);

    std::cout << "TestSignalFilterIC passed." << std::endl;
}

void TestVarianceIC()
{
    // 测试用例 1: 基本的方差计算
    VarianceIC variance_ic(5);
    variance_ic.update(2.0);
    variance_ic.update(4.0);
    variance_ic.update(4.0);
    variance_ic.update(4.0);
    assert(nearlyEqual(variance_ic.update(5.0), 0.96)); // 预期方差为2.0

    // 测试用例 2: 检查周期边界
    VarianceIC variance_ic2(3);
    variance_ic2.update(1.0);
    variance_ic2.update(2.0);
    variance_ic2.update(3.0);
    assert(nearlyEqual(variance_ic2.update(4.0), 0.666667)); // 预期方差为1.0

    // 测试用例 3: 检查重置功能
    variance_ic2.reset();
    variance_ic2.update(5.0);
    assert(nearlyEqual(variance_ic2.update(6.0), 0.25)); // 预期方差为0.5

    // 添加更多测试用例以覆盖其他边缘情况和正常情况

    std::cout << "All VarianceIC tests passed successfully." << std::endl;
}

int main()
{
    TestCircularBufferPushBack();
    TestCircularBufferClear();
    TestCircularBufferOutOfRange();
    TestCircularLenthEqualsOne();

    TestMeanIC();
    TestSumIC();
    TestSmoothIC();
    TestSignalFilterIC();
    TestVarianceIC();

    TestDecisionMakingUnit();
    return 0;
}